package gbench.appdemo.myworld.market.store;

import lombok.Data;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Stream;

import gbench.appdemo.myworld.market.commodity.Commodity;
import gbench.appdemo.myworld.market.commodity.Price;
import gbench.appdemo.myworld.market.trading.TradeBroker;
import gbench.common.tree.LittleTree.IRecord;
import static gbench.common.tree.LittleTree.IRecord.*;

/**
 * 交易者：市场参与者
 * 在线商城
 * @author gbench
 *
 */
@Data
public class OnlineStore {
    
    /**
     * 交易者
     * @param id 交易者Id
     */
    public OnlineStore(String id) {
        this.id = id;
        this.name = id;
    }
    
    /**
      * 增加库存
      * @param name
      * @param quantity
      */
      public void increase(final Commodity commodity, final Number qty) {
          
          quotationManager.computeIfPresent(commodity.getName(), (k,v)->{
              v.setQuantity(v.getQuantity()+qty.doubleValue());
              financeAccounting.increment(commodity, qty);
              return v;
          });
      }

    /**
     * 减少库存
     * @param name
     * @param quantity
     */
     public void decrease(final Commodity commodity, final Number qty) {
         quotationManager.computeIfPresent(commodity.getName(), (k,v)->{
             v.setQuantity(v.getQuantity()-qty.doubleValue());
             this.financeAccounting.decrement(commodity, qty);
             return v;
         });
     }

    /**
      * 加入冻结请求
      * @param name
      * @param quantity
      */
      public void freeze(TradeBroker broker,Commodity commodity,Number qty,Number timeout) {
          this.getQuotationManager().computeIfPresent(commodity.getName(), (k,v)->{
              v.setFreezed(v.getFreezed()+qty.doubleValue());
              financeAccounting.free(commodity, qty);
              taskTodos.add(REC("type","freezed","broker",broker,"commodity",commodity,"quantity",qty,
                    "timeout",timeout.doubleValue()<0?this.getTimeOut(commodity):timeout.longValue(),
                    "time",LocalDateTime.now()));
              return v;
          });
      }

    /**
     * 加入冻结请求
     * 使用默认时长冻结商品
     * @param name
     * @param quantity
     */
     public void freeze(TradeBroker broker,Commodity commodity,Number qty) {
         this.freeze(broker,commodity, qty,-1);
     }

    /**
    * 发货
    * @param name
    * @param quantity
    */
    public void release(Commodity commodity,Number qty) {
        this.getQuotationManager().computeIfPresent(commodity.getName(), (k,v)->{
            v.setReleased(qty.doubleValue());
            financeAccounting.release(commodity, qty);
            return v;
        });
    }

    /**
     * 发货
     * @param name
     * @param quantity
     */
     public void deliver(Commodity commodity,Number qty) {
         this.getQuotationManager().computeIfPresent(commodity.getName(), (k,v)->{
             v.setReleased(qty.doubleValue());
             financeAccounting.deliver(commodity, qty);
             return v;
         });
     }

    /**
     * 发货
     * @param name
     * @param quantity
     */
     public void close(Commodity commodity,Number qty) {
         this.getQuotationManager().computeIfPresent(commodity.getName(), (k,v)->{
             v.setReleased(qty.doubleValue());
             financeAccounting.close(commodity, qty);
             return v;
         });
     }
    
    /**
       * 
       * @param commodity
       * @return
       */
     public long getTimeOut(Commodity commodity) {
         return this.getDefaultTimeOut();
     }
    
    /**
     * 初始化报价单
     * @param name 商品名称
     * @return CommodityProfile
     */
    public CommodityQuotation initializeQuotation(Commodity commodity,Price<Commodity,Commodity>price) {
        final var name = commodity.getName();
        return quotationManager.computeIfAbsent(name, p->{
            final var quantity = Math.random()*10000000;
            final var quotation = new CommodityQuotation(name,quantity,price);
            this.getFinanceAccounting().increment(commodity, quantity);
            return quotation;
        });
    }
    
    /**
     * 获取商品报价单
     * @param name 商品名称
     * @return CommodityProfile
     */
    public CommodityQuotation getQuotation(Commodity commodity) {
        return quotationManager.get(commodity);
    }
    
    /**
     * 
     */
    public String toString() {
        return MessageFormat.format("OnlineStore(id:{0},name:{1})", id,name);
    }
    
    /**
     * 查看商品售卖状态
     * @return
     */
    public List<IRecord> trialBalance(Commodity commodity){
        return this.financeAccounting.trialBalance2(commodity);
    }
    
    /**
     * 产看交易分录
     * @return
     */
    public Stream<IRecord> getTransactions(Commodity commodity){
        return this.financeAccounting.getTransDatabase();
    }
    
    private String id;
    private String name;
    private long defaultTimeOut;
    private QuotationManager quotationManager = new QuotationManager();// 库存
    private TaskTooDos taskTodos = new TaskTooDos();// 待完成事项。
    private FinanceAccounting financeAccounting = new FinanceAccounting(this);

}
